// Copyright 叶湘 ( weixin:yexiang841, email:yexiang841@qq.com ), Shitouren Studio. All Rights Reserved.

#include "Hit/Q3D_CPPC_HitTarget.h"
#include "Hit/Q3D_CPPU_Hit.h"
#include "Logger/Q3D_CPPU_Logger.h"

// Sets default values for this component's properties
UQ3D_CPPC_HitTarget::UQ3D_CPPC_HitTarget()
{
	// Set this component to be initialized when the game starts, and to be ticked every frame.  You can turn these features
	// off to improve performance if you don't need them.
	PrimaryComponentTick.bCanEverTick = true;

	// ...
}

// Called when the game starts
void UQ3D_CPPC_HitTarget::BeginPlay()
{
	Super::BeginPlay();

	// ...
}

void UQ3D_CPPC_HitTarget::EndPlay(const EEndPlayReason::Type EndPlayReason)
{
	Super::EndPlay(EndPlayReason);
	/* 还没到决定要不要这么做的时候
    TArray<UQ3D_CPPU_Hit*> array_values;
    this->Map_Name_To_Ptr_U_Hit.GenerateValueArray( array_values );
    for( UQ3D_CPPU_Hit* one : array_values ){
		one->Q3D_ED_Hit_Done.RemoveAll( this );
		one->Q3D_ED_Hit_Cancel.RemoveAll( this );
		one->Q3D_ED_Halo_Cancel.RemoveAll( this );
		one->Q3D_ED_Hit_Done.RemoveAll( this );
	}
	int32 int_count;
	this->Q3D_F_Hit_Cancel_All( int_count );
	*/
}

// Called every frame
void UQ3D_CPPC_HitTarget::TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction *ThisTickFunction)
{
	Super::TickComponent(DeltaTime, TickType, ThisTickFunction);

	// ...
}

void UQ3D_CPPC_HitTarget::Q3D_F_Hit_Set_Implementation(UQ3D_CPPU_Hit *ptr_u_hit, bool &bool_success, FString &string_log)
{
	// 命中体不能为空
	if (!ptr_u_hit)
	{
		bool_success = false;
		string_log = "Invalid_Ptr_U_Hit";
		Q3D_LOG(Error, string_log);
		return;
	}
	if (this->Map_Name_To_Ptr_U_Hit.Find(ptr_u_hit->Name_Id))
	{
		bool_success = false;
		string_log = "Hit_Duplicate_[" + ptr_u_hit->Name_Id.ToString() + "]";
		Q3D_LOG(Warning, string_log);
		return;
	}
	// Q3D_LOG( Verbose, StaticEnum<EQ3D_CPPE_HitMode>()->GetNameStringByValue( (uint8)(ptr_u_hit->Q3D_F_HitMode_GetEnum()) ) \
	// 				+ "(" + StaticEnum<EQ3D_CPPE_HitType>()->GetNameStringByValue( (uint8)(ptr_u_hit->Q3D_F_HitType_GetEnum()) ) \
	// 				+ ")_On_[" + StaticEnum<EQ3D_CPPE_PropertyName>()->GetNameStringByValue( (uint8)(ptr_u_hit->Enum_PropertyName) ) \
	// 				+ "]_Set_[" + ptr_u_hit->Name_Id.ToString() + "]" );
	this->Map_Name_To_Ptr_U_Hit.Add(ptr_u_hit->Name_Id, ptr_u_hit);
	// 绑定事件用于在 Cancel 或者 Done 之后从 Map 中删除 Hit
	ptr_u_hit->Q3D_ED_Hit_Done.AddDynamic(this, &UQ3D_CPPC_HitTarget::_FD_Hit_Del_ByPtr);
	ptr_u_hit->Q3D_ED_Hit_Cancel.AddDynamic(this, &UQ3D_CPPC_HitTarget::_FD_Hit_Del_ByPtr);
	ptr_u_hit->Q3D_ED_Halo_Done.AddDynamic(this, &UQ3D_CPPC_HitTarget::_FD_Hit_Del_ByPtr);
	ptr_u_hit->Q3D_ED_Halo_Cancel.AddDynamic(this, &UQ3D_CPPC_HitTarget::_FD_Hit_Del_ByPtr);
	// 开始执行
	ptr_u_hit->Q3D_F_Hit_Execute_ByHitTarget(bool_success, string_log);
	if (bool_success)
	{
		Q3D_LOG(Log, string_log);
	}
	else
	{
		Q3D_LOG(Warning, string_log);
	}
	return;
}

void UQ3D_CPPC_HitTarget::Q3D_F_Hit_Cancel_ById(FName name_id, bool &bool_success, FString &string_log)
{
	UQ3D_CPPU_Hit *ptr_u_hit_tmp = this->Map_Name_To_Ptr_U_Hit[name_id];
	if (ptr_u_hit_tmp)
	{
		bool_success = false;
		string_log = "Hit_Missed_[" + name_id.ToString() + "]";
		Q3D_LOG(Warning, string_log);
		return;
	}
	ptr_u_hit_tmp->Q3D_F_Hit_Cancel(bool_success, string_log);
	if (bool_success)
	{
		Q3D_LOG(Log, string_log);
		return;
	}
	else
	{
		Q3D_LOG(Error, string_log);
		return;
	}
	return;
}

void UQ3D_CPPC_HitTarget::Q3D_F_Hit_Cancel_ByType(EQ3D_CPPE_HitType enum_hit_type, int32 &int_count)
{
	int32 int_count_tmp = 0;
	TArray<UQ3D_CPPU_Hit *> array_values;
	this->Map_Name_To_Ptr_U_Hit.GenerateValueArray(array_values);
	for (UQ3D_CPPU_Hit *one : array_values)
	{
		if (enum_hit_type != one->Q3D_F_HitType_GetEnum())
		{
			continue;
		}
		bool bool_success_tmp01;
		FString string_log_tmp01;
		one->Q3D_F_Hit_Cancel(bool_success_tmp01, string_log_tmp01);
		if (bool_success_tmp01)
		{
			Q3D_LOG(Log, string_log_tmp01);
			int_count_tmp += 1;
		}
		else
		{
			Q3D_LOG(Error, string_log_tmp01);
			bool bool_success_tmp02;
			FString string_log_tmp02;
			this->_F_Hit_Del_ById(one->Name_Id, bool_success_tmp02, string_log_tmp02);
			if (bool_success_tmp02)
			{
				int_count_tmp += 1;
			}
		}
	}
	int_count = int_count_tmp;
	return;
}

void UQ3D_CPPC_HitTarget::Q3D_F_Hit_Cancel_ByCauser(EQ3D_CPPE_HitType enum_hit_type, AActor *ptr_a_hit_causer, int32 &int_count)
{
	int32 int_count_tmp = 0;
	TArray<UQ3D_CPPU_Hit *> array_values;
	// 挨个 Value 找过去
	this->Map_Name_To_Ptr_U_Hit.GenerateValueArray(array_values);
	for (UQ3D_CPPU_Hit *one : array_values)
	{
		// 只针对一种 HitType
		if (enum_hit_type != one->Q3D_F_HitType_GetEnum())
		{
			continue;
		}
		// 比对 HitCauser
		if (one->Ptr_A_HitCauser != ptr_a_hit_causer)
		{
			continue;
		}
		bool bool_success_tmp01;
		FString string_log_tmp01;
		// 若找到就让 Hit 自己 Cancel
		one->Q3D_F_Hit_Cancel(bool_success_tmp01, string_log_tmp01);
		// 日志
		if (bool_success_tmp01)
		{
			// Cancel 若成功会触发 Del 委托
			Q3D_LOG(Log, string_log_tmp01);
			int_count_tmp += 1;
		}
		else
		{
			Q3D_LOG(Error, string_log_tmp01);
			bool bool_success_tmp02;
			FString string_log_tmp02;
			// Cancel 不成功不会出发 ED 事件，需要手动删除
			this->_F_Hit_Del_ById(one->Name_Id, bool_success_tmp02, string_log_tmp02);
			if (bool_success_tmp02)
			{
				int_count_tmp += 1;
			}
		}
	}
	int_count = int_count_tmp;
	return;
}

void UQ3D_CPPC_HitTarget::Q3D_F_Hit_Cancel_All(int32 &int_count)
{
	int32 int_count_tmp = 0;
	TArray<UQ3D_CPPU_Hit *> array_values;
	this->Map_Name_To_Ptr_U_Hit.GenerateValueArray(array_values);
	for (UQ3D_CPPU_Hit *one : array_values)
	{
		bool bool_success_tmp01;
		FString string_log_tmp01;
		one->Q3D_F_Hit_Cancel(bool_success_tmp01, string_log_tmp01);
		if (bool_success_tmp01)
		{
			Q3D_LOG(Log, string_log_tmp01);
			int_count_tmp += 1;
		}
		else
		{
			Q3D_LOG(Error, string_log_tmp01);
			bool bool_success_tmp02;
			FString string_log_tmp02;
			this->_F_Hit_Del_ById(one->Name_Id, bool_success_tmp02, string_log_tmp02);
			if (bool_success_tmp02)
			{
				int_count_tmp += 1;
			}
		}
	}
	int_count = int_count_tmp;
	return;
}

void UQ3D_CPPC_HitTarget::_F_Hit_Del_ById(FName name_id, bool &bool_success, FString &string_log)
{
	if (!this->Map_Name_To_Ptr_U_Hit.Remove(name_id))
	{
		bool_success = false;
		string_log = "Hit_Missed_[" + name_id.ToString() + "]";
		Q3D_LOG(Error, string_log);
		return;
	}
	bool_success = true;
	string_log = "Hit_Del_[" + name_id.ToString() + "]";
	// Q3D_LOG( Verbose, string_log );
	return;
}

void UQ3D_CPPC_HitTarget::_FD_Hit_Del_ByPtr(UQ3D_CPPU_Hit *ptr_u_hit)
{
	if (!ptr_u_hit)
	{
		Q3D_LOG(Error, "Invalid_Ptr_U_Hit");
		return;
	}
	bool bool_success;
	FString string_log;
	this->_F_Hit_Del_ById(ptr_u_hit->Name_Id, bool_success, string_log);
}
